Matroid & Greedy Algorithm

매트로이드(Matroid)
M(S,l) 1. S는 유한 집합이다. 2. lS의 독립적(independent)부분집합들로 구성된 공집합이 아닌 집합이다. 독립적 부분 집합은 l이고 AB이면 Al이라고 말한다. l이 이런 특성을 만족시키면 상속성(hereditary)가 있다고 말한다. 여기서 공집합 은 반드시 l의 원소임 3. Al,Bl,|A|<|B|A{x}lxBA가 존재한다. M이 교환 특성(exchange property)을 만족시킨다고 말한다.
그래픽 매트로이드(Graphic Matroid)
MG=(SG,lG) about 무방향 그래프G=(V, E) - SG는 G의 간선들의 집합인 E - A가 E의 부분집합일 때, A가 비순환(acyclic)이라는 것은 AlG의 필요충분조건이다. 부분 그래프 GA(V,A)가 포리스트를 이룬다는 것은 간선들의 집합 A가 독립적이라는 조건의 필요충분조건이다. G=(V, E)가 무방향 그래프이면, MG=(SG,lG) 매트로이드이다.
M=(S,l)에서 원소 xA가 A에 더해져도 독립성을 유지할 수 있다면 원소 x를 Al의 확장(extension)이라고 한다. A가 아무런 확장도 가지고 있지 않다면 최대(maximal)라고 말한다. 하나의 매트로이드 안에 있는 모든 최대 독립 부분 집합들은 크기가 같다. 그리픽 매트로이드에서 최대인 상태는 G의 모든 점을 |V|-1 개의 간선을 가진 자유 트리 == 신장 트리(spanning tree)
// Psudo code
Greedy(M, w):
A=emptySet;
M.S w
for(x \in M.S): // w(x)
if A \cup {x} \in M.l:
A=A \cup {x};
return A;
Unit-time task scheduling with Matroid
n개의 단위 시간 작업을 가지는 S={a_1, a_2, … , a_n};
n개의 정수 형태 최종 마감 시간(deadline) d_1, d_2, … , d_n의 집합;        1=\leq d_i \leq n
n개의 음수가 아닌 가중치(weight or penalty) w_1, w_2, w_3, …, w_n의 집합
#include <iostream>
#include <algorithm>
struct Act{
int s, d, w;
Act(){}
Act(int _s, int _d, int _w): s(_s), d(_d), w(_w) {}
~Act(){}
void set(int _s, int _d, int _w){
this->s=_s;
this->d=_d;
this->w=_w;
}
};
bool ActCmp(Act act1, Act act2){
return act1.w>act2.w;
}
struct Acts{
Act* arr;
int size, cap=0;
Acts(int _size): size(_size) {
this->arr=new Act[this->size];
}
void insert(int _s, int _d, int _w){
if(cap==size){
std::cout<<"Acts Full"<<std::endl;
exit(1);
}
arr[cap++].set(_s, _d, _w);
}
void sort(void){
std::sort(arr, arr+size, ActCmp);
}
int s(int ind){
return this->arr[ind].s;
}
int d(int ind){
return this->arr[ind].d;
}
int w(int ind){
return this->arr[ind].w;
}
};
struct Array{
int* arr;
int sz, cap=0;
Array(int _sz): sz(_sz) {
arr=new int[sz];
}
void insert(int ind){
this->arr[this->cap++]=ind;
}
void print(void){
for(int i=0; i<this->cap; ++i) std::cout<<arr[i]<<' ';
std::cout<<std::endl;
}
};
void GreedyActivitySelector(Acts acts, Array& index){
acts.sort();
int n=acts.size;
int ind=0;
int l=0;
for(int m=0; m<n; ++m){
int sum=0;
for(int k=0; k<=m; ++k){
if(acts.d(k)<=l) sum++;
}
if(sum<=m){
index.insert(m+1);
l++;
}
}
}
int main(void){
Acts acts(7);
Array index(7);
int s[7]={1, 2, 3, 4, 5, 6, 7};
int d[7]={4, 2, 4, 3, 1, 4, 6};
int w[7]={70, 60, 50, 40, 30, 20, 10};
for(int i=0; i<7; ++i) acts.insert(s[i], d[i], w[i]);
acts.sort();
GreedyActivitySelector(acts, index);
index.print();
return 0;
}
크기 순으로 정렬한 이후, Nt(A)t를 만족하는 경우에만 추가 모든 t에 대해서 Nt(A)t를 만족하는 집합 A는 독립적이다.(모두 가능)